/*
 * postjson.js
 * @author itea 2010-04-16
 * @version 0.9.2 2010-09-02
 * requires: jQuery
 */

(function($){
// BEGIN

var _seq = 100;
var _map = {};
var Postjson = function(arg) {
	if(this == window) { // function call
	} else { // constructor
		this.$seq = _seq++;
		this._idx = 0;
		this._calls = [];
		this.options = $.extend({}, Postjson.options);
		if(typeof arg == 'string')
			this.options.methodPrefix = $.trim(arg);
	}
};
Postjson.options = {};

Postjson.setup = function (options) {
	$.extend(Postjson.options, options);
};

Postjson.prototype = {
	_genJson: function() {
		var json = {};
		json.calls = [];
		for(var i=0; i<this._calls.length; i++)
			json.calls.push({
				idx: this._calls[i].idx,
				method: this._calls[i].method,
				data: this._calls[i].data
			});
		json.seq = this.$seq;
		json.clientTime = new Date().valueOf();
		json.userAgent = navigator.userAgent || null;
		return JSON.stringify(json);
	},
	/* args form-1: [url[, error_callback]]
	 * args form-2: [error_callback]
	 * args form-3: [options]
	 */
	request: function(arg) {
		var options = {};
		if(typeof arg == 'string') {
			options.url = arg;
			if(arguments.length > 1 && typeof arguments[1] == 'function')
				options.error = arguments[1];
		} else if(typeof arg == 'function') {
			options.error = arg;
		} else if(typeof arg == 'object') {
			$.extend(options, arg);
		}
		var opt = $.extend({}, this.options, options, {
			type: 'POST',
			success: this._ajaxSuccess, 
			context: this, 
			dataType: 'json',
			data: this._genJson()
				});
		$.ajax(opt);
	},
	_ajaxSuccess: function(data, textStatus, XMLHttpRequest) {
		data.returns.sort(function(a, b){return a.idx - b.idx;});
		for(var i=0; i<data.returns.length; i++) {
			this._dealReturn(data.returns[i]);
		}
	},
	_dealReturn: function(rtn) {
		var call = this._calls[rtn.idx];
		if(!call || call.idx != rtn.idx) alert('Oops, something wrong!');
		if(call.callback)
			call.callback.call(call.context || window, rtn.state, rtn.result);
	},
	/*
	 * args form: method, data[, callback] [, context]
	 */
	call: function(method) {
		var call = {};
		call.method = (this.options.methodPrefix || '') + (method || '');
		call.data = [];
		for(var i=1; i<arguments.length; i++) {
			var arg = arguments[i];
			if(typeof arg == 'function') {
				call.callback = arg;
				if(i< arguments.length -1)
					call.context = arguments[i+1];
				break;
			} else
				call.data.push(arg);
		}
		call.idx = this._idx++;
		this._calls.push(call);
		return this;
	}
};

if(!window.Postjson)
	window.Postjson = Postjson;

// END
})(jQuery);
